package org.fhm.zdte.protocol.zrudp.standard;

import org.fhm.zdte.common.ability.ITirConsumer;
import org.fhm.zdte.common.protocol.AbstractMessageStandard;

import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Supplier;

/**
 * The interface <b>IDataConvertor</b>'s implementation is used to convert between Packet-Message and Packet-Data.
 *
 * @author 谭波
 * @since 2024/2/1
 */
public interface IDataConvertor<R> {

    /**
     * Obtain a pipeline converting Packet-Message to Packet-Data.
     *
     * @param supplier Obtain a conversion basis.
     * @return Convertor that is converting Packet-Message to Packet-Data.
     */
    IPipeline<R> ofPipeline(Supplier<R[]> supplier);

    /**
     * Obtain a pipeline converting Packet-Data to Packet-Message.
     *
     * @param supplier Obtain a conversion basis.
     * @return Convertor that is converting Packet-Data to Packet-Message.
     */
    IConvertor<R> ofConvertor(Supplier<R[]> supplier);

    /**
     * The interface <b>IPipeline</b>'s implementation is used to convert Packet-Message to Packet-Data.
     *
     * @param <R> Conversion basis.
     */
    interface IPipeline<R> {

        /**
         * Join a process that how to convert Packet-Message to Packet-Data.
         *
         * @param function Process.
         * @return Convertor Packet-Message to Packet-Data.
         */
        IPipeline<R> joinFor(BiConsumer<R, List<Byte>> function);

        /**
         * Generate finally Byte-Array.
         *
         * @return Byte-Array.
         */
        byte[] generation();

    }

    /**
     * The interface <b>IPipeline</b>'s implementation is used to convert Packet-Data to Packet-Message.
     *
     * @param <R> Conversion basis.
     */
    interface IConvertor<R> {

        /**
         * Prepare Packet-Message and process that how to obtain <b>Collection-With-Head</b> from Packet-Message.
         *
         * @param supplier how to obtain <b>Collection-With-Head</b> from Packet-Message.
         * @param message  Packet-Message.
         * @return Convertor is used to convert Packet-Data to Packet-Message.
         */
        IConvertor<R> prepare(Supplier<List<List<Byte>>> supplier, AbstractMessageStandard message);

        /**
         * Set a process that matches between Packet-Head and byte.
         *
         * @param matchFunction Process that match between Packet-Head and byte.
         * @return Convertor is used to convert Packet-Data to Packet-Message.
         */
        IConvertor<R> setMatchFunction(BiFunction<R, Byte, Boolean> matchFunction);

        /**
         * The beginning will convert Packet-Data from Packet-Message.
         *
         * @param function Process that converts Packet-Message-Member to Byte-Array.
         */
        void makeFor(ITirConsumer<R, AbstractMessageStandard, List<Byte>> function);

    }
}
